package com.cx.jvm;

import java.lang.ref.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author:cxy
 * @Date:2020/8/23 16:58
 */
public class Refrence {


    public static void main(String[] args) {
//        strong();
//        soft();
//        weak();
        p();
    }

    public static void strong(){
        /** 强 普通引用 */
        Object o = new Object();
    }

    public static void soft(){
        /**  run -Xmx20M  软引用 遇到gc的时候判断是否堆内存够用 如果不够用则被回收 */
        /** 适合做缓存 */
        SoftReference<byte[]> reference = new SoftReference<>(new byte[1024*1024*10]);

        System.out.println(reference.get());
        System.gc();

        try { TimeUnit.SECONDS.sleep(1); } catch (Exception e) { e.printStackTrace(); }
        System.out.println(reference.get());
        byte[] bytes = new byte[1024 * 1024 * 12];
        System.out.println(reference.get());

    }


    public static void weak(){
        /** 弱引用 遇到gc就被回收 */
        WeakReference<R> reference = new WeakReference<R>(new R());

        System.out.println(reference.get());
        System.gc();
        System.out.println(reference.get());
        /**
         * ThreadLocal 存的是  key:Thread(当前线程) -- value:Entry(ThreadLocal:value)
         * ThreadLocal.ThreadLocalMap.Entry 采用弱引用
         * 强引用会出现内存泄漏问题 如果 tl = null 则Entry:key依然指向 ThreadLocal,不会被回收所以内存泄漏
         * 使用弱引用 如果 tl = null 则Entry:key弱引用会被回收 k=null,但是value永远不会被访问到,依然存在内存泄漏
         *  正确做法是使用完后 remove()掉 Entry
         */
        ThreadLocal<R> tl = new ThreadLocal<>();
        tl.set(new R());
        tl.remove();
    }

    /**
     * 虚引用
     */
    public static void p()  {
        ReferenceQueue<R> queue = new ReferenceQueue<R>();
        R r = new R();
        PhantomReference<R> reference = new PhantomReference<>(r,queue);
        reference.get();

        new Thread(()->{
            while (true){
                Reference<? extends R> poll = queue.poll();
                if(poll!=null){
                    System.out.println("被回收了---"+ poll.get());
                }
            }
        },"Phantom").start();
        r = null;
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.gc();
    }

    static class R{

    }

}
